(function ($) {
    "use strict";

    $.fn.tautocomplete = function (options, callback) {

        // default parameters
        var settings = $.extend({
            width: "500px",
            columns: [],
            formatColumns:"",
            onchange: "",
            norecord: "No Records Found",
            dataproperty: null,
            regex: "^[a-zA-Z0-9\b]+$",
            data: null,
			url:null,
			//传递的参数方法
			queryParams:function (params){
				params = {
					pageSize : params.limit,
					pageNum : (params.offset / params.limit) + 1
				}
				return params;
			},
			pageSize : 10,
			pageList : [10,25,50,100],
			//输入的查询字段，如拼音码，五笔码
			queryFiled : "search_chinaSpell",
            placeholder : null,
            theme: "default",
			moveClass:"glyphicon glyphicon-remove"
        }, options);
        
        var cssClass = [["default", "adropdown"], ["classic", "aclassic"], ["white", "awhite"]];

        // set theme
        cssClass.filter(function (v, i) {
            if (v[0] == settings.theme) {
                settings.theme = v[1];
                return;
            }
        });
        
        // initialize DOM elements
        var el = {
            ddDiv: $("<div>", { class: settings.theme }),
            ddTable: $("<table></table>", { style: "width:" + settings.width }),
            ddTableCaption: $("<caption>" + settings.norecord + "</caption>"),
            ddTextbox: $("<input type='text' class='form-control'>")
        };
		
        var keys = {
            UP: 38,
            DOWN: 40,
            ENTER: 13,
            TAB: 9
        };

        var errors = {
            columnNA: "Error: Columns Not Defined",
            dataNA: "Error: Data Not Available"
        };
        
        // plugin properties
        var tautocomplete = {
            row: function () {
                return el.ddTextbox.data("row");
            },
            searchdata: function () {
                return el.ddTextbox.val();
            },
            isNull: function () {
                if (el.ddTextbox.data("id") == "")
                    return true;
                else
                    return false;
            }
        };

        // delay function which listens to the textbox entry
        var delay = (function () {
            var timer = 0;
            return function (callsback, ms) {
                clearTimeout(timer);
                timer = setTimeout(callsback, ms);
            };
        })();

        var focused = false;

        // check if the textbox is focused.
        if (this.is(':focus')) {
            focused = true;
        }

        // get number of columns
        var cols = settings.columns.length;

        var orginalTextBox = this;

        // wrap the div for style
        this.wrap("<div class='acontainer'></div>");

        // create a textbox for input
        this.after(el.ddTextbox);
        el.ddTextbox.attr("autocomplete", "off");
        el.ddTextbox.css("width", this.width + "px"); 
        el.ddTextbox.css("font-size", this.css("font-size"));
        el.ddTextbox.attr("placeholder", settings.placeholder);

        // check for mandatory parameters
        if (settings.columns == "" || settings.columns == null) {
            el.ddTextbox.attr("placeholder", errors.columnNA);
        }
        //else if (settings.data == "" || settings.data == null) {
            //el.ddTextbox.attr("placeholder", errors.dataNA);
        //}

        // append data property
        if (settings.dataproperty != null) {
            for (var key in settings.dataproperty) {
                el.ddTextbox.attr("data-" + key, settings.dataproperty[key]);
            }
        }

        // append div after the textbox
        this.after(el.ddDiv);

        // hide the current text box (used for stroing the values)
        this.hide();

        // append table after the new textbox
        el.ddDiv.append(el.ddTable);
        el.ddTable.attr("cellspacing", "0");

        // append table caption
        el.ddTable.append(el.ddTableCaption);

        // create table columns
        /*var header = "<thead><tr>";
        for (var i = 0; i <= cols - 1; i++) {
            header = header + "<th>" + settings.columns[i] + "</th>"
        }
        header = header + "</thead></tr>"
        el.ddTable.append(header);*/

        // assign data fields to the textbox, helpful in case of .net postbacks
        {
            var id = "", text = "";

            if (this.val() != "") {
                var val = this.val().split("#$#");
                id = val[0];
                text = val[1];
            }

            el.ddTextbox.attr("data-id", id);
            el.ddTextbox.attr("data-text", text);
            el.ddTextbox.val(text);
        }

        if (focused) {
            el.ddTextbox.focus();
        }

        // event handlers
        
        //给input注册事件阻止事件冒泡到table和document
		el.ddTextbox.on('mousedown click dbclick',function (event){
			event.stopPropagation();
		})
        
        // autocomplete key press
        el.ddTextbox.keyup(function (e) {
        	event.stopPropagation();
            //return if up/down/return key
            if ((e.keyCode < 46 || e.keyCode > 90) && (e.keyCode != 8)) {
                e.preventDefault();
                return;
            }

            //delay for 1 second: wait for user to finish typing
            delay(function () {
                if (el.ddTextbox.val() == "") {
					el.ddDiv.hide();
                    return;
                }
                if (el.ddTextbox.val().length<2) {
                    return;
                }
                
				el.ddDiv.show();

                // hide no record found message
                el.ddTableCaption.hide();

                //el.ddTextbox.addClass("loading");
				el.ddTable.bootstrapTable("destroy");
				
				//创建table
				el.ddTable.bootstrapTable({
					pagination:true,
					strictSearch:true,
					columns:settings.columns,
					sidePagination:'server',
					url:settings.url,
					pageSize : settings.pageSize,
					pageList :settings.pageList,
					queryParams:function (params){
						var p = settings.queryParams.call(this,params);
						p[settings.queryFiled] = el.ddTextbox.val();
						return p;
					}
				})
				showDropDown();

                /*if ($.isFunction(settings.data)) {
                    var data = settings.data.call(this);
                    jsonParser(data);
                }
                else {
                    // default function
                }*/
            }, 500);
        });

        // do not allow special characters
        el.ddTextbox.keypress(function (event) {
        	event.stopPropagation();
            var regex = new RegExp(settings.regex);
            var key = String.fromCharCode(!event.charCode ? event.which : event.charCode);

            if (!regex.test(key)) {
                event.preventDefault();
                return false;
            }
        });

        // textbox keypress events (return key, up and down arrow)
        el.ddTextbox.keydown(function (e) {
        	event.stopPropagation();
            var tbody = el.ddTable.find("tbody");
            var selected = tbody.find("._selected");

            if (e.keyCode == keys.ENTER) {
                e.preventDefault();
				var index=selected.index();
				var row = el.ddTable.bootstrapTable("getData")[index];
				select(row);
                
            }
            if (e.keyCode == keys.UP) {
				e.preventDefault();
                el.ddTable.find("._selected").removeClass("_selected");
                if (selected.prev().length == 0) {
                    tbody.find("tr:last").addClass("_selected");
                } else {
                    selected.prev().addClass("_selected");
                }
            }
            if (e.keyCode == keys.DOWN) {
				e.preventDefault();
                tbody.find("._selected").removeClass("_selected");
                if (selected.next().length == 0) {
                    tbody.find("tr:first").addClass("_selected");
                } else {
                    selected.next().addClass("_selected");
                }
            }
        });
		
		//tr 选中事件
		el.ddTable.on('click-row.bs.table', function (e,row, element, field) {
			select(row);
		});
		
		// row click event
        el.ddTable.delegate("tbody tr", "mouseover", function () {
        	event.stopPropagation();
            el.ddTable.find("._selected").removeClass("_selected");
            $(this).addClass("_selected");
        });
	
		//给div注册事件阻止事件冒泡到table和document
		el.ddDiv.on('mousedown click dbclick',function (event){
			event.stopPropagation();
		})
		
		$(document).off('mousedown',doc_mousedown);
		// 给document注册事件，当点击时隐藏
        $(document).on('mousedown',doc_mousedown);
		//执行后即取消事件注册
		function doc_mousedown(e){
			var event = e || window.e;
			var $target = $(e.target);
			if($target.hasClass(settings.moveClass)){
				return ;
			}
            hideDropDown();
			clear();
			//onChange();
			$(document).off('mousedown',doc_mousedown);
		}
		
		function clear(){
			el.ddTextbox.val("");
		}
		
        function select(row) {
        	var f_row ;
            if ($.isFunction(settings.formatColumns)) {
            	f_row = settings.formatColumns.call(this,row);
            }else{
            	f_row = row
            }
            el.ddTextbox.data("row",f_row);
            hideDropDown();
            onChange();
            //el.ddTextbox.focus();
        }

        function onChange()
        {
            // onchange callback function
            if ($.isFunction(settings.onchange)) {
                settings.onchange.call(this);
            }
            else {
                // default function for onchange
            }
        }

        function hideDropDown() {
            //el.ddTable.hide();
			el.ddDiv.hide();
            el.ddTextbox.removeClass("inputfocus");
            el.ddDiv.removeClass("highlight");
            el.ddTableCaption.hide();
        }

        function showDropDown() {

            var cssTop = (el.ddTextbox.height() + 20) + "px 1px 0px 1px";
            var cssBottom = "1px 1px " + (el.ddTextbox.height() + 20) + "px 1px";

            // reset div top, left and margin
            el.ddDiv.css("top", "0px");
            el.ddDiv.css("left", "0px");
            el.ddTable.css("margin", cssTop);

            el.ddTextbox.addClass("inputfocus");
            el.ddDiv.addClass("highlight");
            el.ddTable.show();

            // adjust div top according to the visibility
            if (!isDivHeightVisible(el.ddDiv)) {
                el.ddDiv.css("top", -1 * (el.ddTable.height()) + "px");
                el.ddTable.css("margin", cssBottom);
                if (!isDivHeightVisible(el.ddDiv)) {
                    el.ddDiv.css("top", "0px");
                    el.ddTable.css("margin", cssTop);
                    $('html, body').animate({
                        scrollTop: (el.ddDiv.offset().top - 60)
                    }, 250);
                }
            }
            // adjust div left according to the visibility
            if (!isDivWidthVisible(el.ddDiv)) {
                el.ddDiv.css("left", "-" + (el.ddTable.width() - el.ddTextbox.width() - 20) + "px");
            }
        }
        return tautocomplete;
    };
}(jQuery));

function isDivHeightVisible(elem) {
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();

    var elemTop = $(elem).offset().top;
    var elemBottom = elemTop + $(elem).height();

    return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom)
      && (elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}
function isDivWidthVisible(elem) {
    var docViewLeft = $(window).scrollLeft();
    var docViewRight = docViewLeft + $(window).width();

    var elemLeft = $(elem).offset().left;
    var elemRight = elemLeft + $(elem).width();

    return ((elemRight >= docViewLeft) && (elemLeft <= docViewRight)
      && (elemRight <= docViewRight) && (elemLeft >= docViewLeft));
}

//结合bootstrap_table再封装
//构建可自动完成表格控件
function create_autocomplete_table(settings){
	//表格jquery对象
	var $table = settings.$table;
	//表格初始数据
	var init_data = settings.init_data;
	//表格参数
	var options = settings.options;
	//自动完成表格参数
	var tautocomplete_options = settings.tautocomplete_options;
	//弹出提示框
	var layer = settings.layer;
	//tautocomplete fields,可以自动完成的字段名称集合
	var tautocomplete_fields = settings.tautocomplete_fields;
	//input fields，可以input填写的字段名称集合
	var input_fields = settings.input_fields;
	//input fields 验证规则和提示文字
	var input_fields_reg = settings.input_fields_reg;
	//select fields，select的字段名称集合
	var select_fields = settings.select_fields;
	// enter fields，enter键字段集合，按顺序排列
	var enter_fields = settings.enter_fields;
	//触发事件名称
	var event_name = settings.event_name;
	var f_callback = settings.callback;
	var f_formatColumns = settings.formatColumns;
	$table.bootstrapTable(options);
	//table事件
	$table.on(event_name, function (e,field, value, row, element) {
		var $td =$(element);
		var index=$td.parent("tr").data("index");
		if($.inArray(field, tautocomplete_fields)>-1){
			// 创建替换的input 对象
			var $input = $("<input type='text'>");
			$(element).html($input);
			var tautocomplete = $input.tautocomplete($.extend({
				onchange: function () {
					var inputV="";
					var row =tautocomplete.row();
					//获取tr在表格中的序号
					$table.bootstrapTable('updateRow', {index: index, row: row});
					//有内容输入获取跳到下一项,没有继续自身获焦
					if(row){
						//下一项获焦
						next_focus(enter_fields,field,$table,index);
					}else{
						//自身获焦
						$.each(enter_fields, function(i, n){
							if(field==n.field){
								var $el = $table.find('tbody tr').eq(index).find("td").eq(enter_fields[i].index);
								if($el.children().length==0){
									$el.click();
								}
							}
						});
					}
				}
			},tautocomplete_options));
			//使input获取焦点
			$input.siblings("input").focus();
		}else if($.inArray(field, input_fields)>-1){
			// 获取$td中的文本内容
			var text = $td.text();
		   // 创建替换的input 对象  
			var $input = $("<input type='text' class='form-control'>").css({"width":$td.width()}).val(text);
			$td.html($input);
			$input.focus();
			$input.keydown(function(event){
				//当前用户按下的键值
				var myEvent = event || window.event;//获取不同浏览器中的event对象
				var kcode = myEvent.keyCode;
				var $this = $(this);
				//判断是否是回车键按下
				if(kcode == '13'){
					$.each(input_fields_reg, function(i, n){
						if(field==n.field){
							var field_reg= input_fields_reg[i].reg;
							var field_msg= input_fields_reg[i].msg;
							var boo = false;
							if(field_reg==""){
								boo=true;
							}else{
								try{
									boo= new RegExp(field_reg).test($this.val());
								}catch(err){
									layer.msg("正则表达式错误");
								}
							}
							if(boo){
								$td.html($this.val());
								row[field]=$this.val();
								$table.bootstrapTable('updateRow', {index: index, row: row});
								//下一项获焦
								next_focus(enter_fields,field,$table,index);
							}else{
								layer.msg(field_msg);
								$input.select();
							}
						}
					});
				}
			});
			//失去焦点
			$input.blur(function(){
				var $this = $(this);
				$.each(input_fields_reg, function(i, n){
					if(field==n.field){
						var field_reg= input_fields_reg[i].reg;
						var field_msg= input_fields_reg[i].msg;
						var boo = false;
						if(field_reg==""){
							boo=true;
						}else{
							try{
								boo= new RegExp(field_reg).test($this.val());
							}catch(err){
								layer.msg("正则表达式错误");
							}
						}
						if(!boo){
							$this.val(""); 
						}
						$td.html($this.val());
						row[field]=$this.val();
						$table.bootstrapTable('updateRow', {index: index, row: row});
					}
				});
				if ($.isFunction(f_callback)) {
		            f_callback.call(this);
				}
				else {
					// default function
				}
			})
			
		}else if($.inArray(field, select_fields)>-1){
			var $select = $td.children("select");
			$select.unbind();
            $select.click(function(event){
                event.stopPropagation();
            })
			$select.change(function(event){
				//设置option状态
				var v = $select.val();
				$select.children('option').each(function(){
					if($(this).val()==v){
						$(this).attr("selected","selected");
						$(this).siblings().removeAttr("selected","selected");
					}
				})
				//更新table row数据
				var data = $table.bootstrapTable('getData');
				var index = $select.parents("tr:first").index();
				var row = data[index];
				row[field] = $select.parent().html();
				row[field+"_V"] = $select.val();
				$table.bootstrapTable('updateRow', {index: index, row: row});
				//下一项获焦
				next_focus(enter_fields,field,$table,index);
				
			})
			openSelect($select);
		}else{
			//layer.msg("这里不能修改");
		}
		if ($.isFunction(f_callback)) {
            f_callback.call(this);
		}
		else {
			// default function
		}
	});
}

function openSelect(elem) {
	if (document.createEvent) {
		var e = document.createEvent("MouseEvents");
		e.initMouseEvent("mousedown", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
		elem[0].dispatchEvent(e);
	} else if (element.fireEvent) {
		elem[0].fireEvent("onmousedown");
	}
}


function next_focus(enter_fields,field,$table,index){
	$.each(enter_fields, function(i, n){
		if(field==n.field){
			if(i<=enter_fields.length-2){
				var next_field_index= enter_fields[i+1].index;
				var $next = $table.find('tbody tr').eq(index).find("td").eq(next_field_index);
				$next.click();
			}else{
				var next_field_index= enter_fields[0].index;
				if($table.find('tbody tr').eq(index+1).length==0){
					$table.bootstrapTable('append', deepcopy(init_data));
				}
				$table.find('tbody tr').eq(index+1).find("td").eq(next_field_index).click();
			}
		}
	});
}


function changeSelect(el,tableId,field){
	var v = $(el).val();
	//更新table row数据
	var data = Page.getJquery("#"+tableId).bootstrapTable('getData');
	var index = $(el).parents("tr:first").index();
	var row = data[index];
	row[field] = v;
	Page.getJquery("#"+tableId).bootstrapTable('updateRow', {index: index, row: row});
	Page.getJquery("#"+tableId).find('tbody tr').eq(0).find("td").eq(6).click();
}

function changeSelectByValue(selectHtml,v){
	var $div=$("<div></div>");
	var $select = $(selectHtml);
	$select.children('option').each(function(){
		if($(this).val()==v){
			$(this).attr("selected","selected");
			$(this).siblings().removeAttr("selected","selected");
		}
	})
	$div.append($select);
	return $div.html();
}


//拷贝对象方法
function deepcopy(obj){
	var a = new Array();
	a[0] = $.extend(true, {}, obj)[0];
	return a;
}
